#include "Ticker.h"
#if TICKER_TASK_MAX

static ticker_datas_t _tic_dat[TICKER_TASK_MAX];
static ticker_cb_t delay_cb = NULL;
static ticker_event_t delay_userdata;
static int32_t ticker_delay_t = 0;
static uint8_t task_max_num = 0;
static uint8_t ticker_init_flg = 0;
static uint32_t timer_count = 0;
static uint32_t (*_timer_get_count)() = NULL;
static ticker_timer_count_mode _count_mode;
static uint32_t tic_count = 0;
static uint8_t tic_flg = 0;

void ticker_attach_timer_count_cb(uint32_t (*timer_get_count)(), ticker_timer_count_mode count_mode)
{
    _timer_get_count = timer_get_count;
    _count_mode = count_mode;
}

void ticker_detach_timer_count_cb()
{
    _timer_get_count = NULL;
}

void ticker_attach_delay_cb(ticker_cb_t call_back, void *userdata)
{
    delay_cb = call_back;
    delay_userdata.userdata = userdata;
}

void ticker_detach_delay_cb()
{
    delay_cb = NULL;
}

ticker_handle_t ticker_attch_ms(uint32_t million, ticker_cb_t call_back, int16_t count, void *userdata)
{
    static uint8_t i;

    if (ticker_init_flg == 0) // 初始化
    {
        ticker_init_flg = 1;
        for (i = 0; i < TICKER_TASK_MAX; i++)
        {
            _tic_dat[i].tick_p = NULL;
            _tic_dat[i].detach_cb = NULL;
            _tic_dat[i].tick_t_mode_flg = -1;
        }
    }
    if (count < 0)
        return NULL;
    if (call_back == NULL)
        return NULL;
    if (million == 0)
        return NULL;

    for (i = 0; i < TICKER_TASK_MAX; i++)
    {
        if (_tic_dat[i].tick_p == NULL) // 找到空任务
        {
            _tic_dat[i].tick_p = call_back;                                  // 注册回调函数
            _tic_dat[i].tick_t_count = 0;                                    // 更新计数
            _tic_dat[i].tick_t_count_max = million;                          // 更新定时
            _tic_dat[i].tick_t_mode_flg = count;                             // 更新次数
            _tic_dat[i].ticker_userdata.handle = (const void *)&_tic_dat[i]; // 获取句柄地址
            _tic_dat[i].ticker_userdata.userdata = userdata;                 // 更新用户指针
            if (i >= task_max_num)                                           // 扫描上限
                task_max_num = i + 1;
            return _tic_dat[i].ticker_userdata.handle; // 返回句柄
        }
    }
    return NULL;
}

ticker_handle_t ticker_attch(uint16_t second, ticker_cb_t call_back, int16_t count, void *userdata)
{
    return ticker_attch_ms((uint32_t)second * 1000, call_back, count, userdata);
}

uint8_t ticker_attch_detach_cb(ticker_handle_t handle, ticker_cb_t call_back, void *userdata)
{
    ticker_datas_t *tmp = (ticker_datas_t *)handle;
    if (handle == NULL)
        return 0;
    if (tmp->tick_p == NULL)
        return 0;
    tmp->detach_cb = call_back;
    return 1;
}

void ticker_detach(ticker_handle_t handle)
{
    ticker_datas_t *tmp = (ticker_datas_t *)handle;
    if (handle == NULL)
        return;
    if (tmp->tick_p == NULL)
        return;
    if (tmp->detach_cb != NULL)
        tmp->detach_cb(&tmp->ticker_userdata);
    tmp->tick_p = NULL;
    tmp->detach_cb = NULL;
    tmp->tick_t_mode_flg = -1;
}

/**
 * @brief 暂停任务
 *
 * @param handle 册时返回的句柄
 */
void ticker_pause(ticker_handle_t handle)
{
    ticker_datas_t *tmp = (ticker_datas_t *)handle;
    if (handle == NULL)
        return;
    if (tmp->tick_p == NULL)
        return;
    if (tmp->tick_t_mode_flg < 0) // 已经暂停
        return;
    tmp->tick_t_mode_flg = -tmp->tick_t_mode_flg - 1; //-1 -- -32768
}

/**
 * @brief 恢复任务
 *
 * @param handle 册时返回的句柄
 */
void ticker_resume(ticker_handle_t handle)
{
    ticker_datas_t *tmp = (ticker_datas_t *)handle;
    if (handle == NULL)
        return;
    if (tmp->tick_p == NULL)
        return;
    if (tmp->tick_t_mode_flg >= 0) // 已经暂停
        return;
    tmp->tick_t_mode_flg = -tmp->tick_t_mode_flg - 1; //-1 -- -32768
}

/**
 * @brief 重置任务计时
 *
 * @param handle 册时返回的句柄
 */
void ticker_reset(ticker_handle_t handle)
{
    ticker_datas_t *tmp = (ticker_datas_t *)handle;
    if (handle == NULL)
        return;
    if (tmp->tick_p == NULL)
        return;
    tmp->tick_t_count = 0;
}

void ticker_change_time(ticker_handle_t handle, uint32_t ms)
{
    ticker_datas_t *tmp = (ticker_datas_t *)handle;
    if (handle == NULL)
        return;
    if (tmp->tick_p == NULL)
        return;
    tmp->tick_t_count = 0;
    tmp->tick_t_count_max = ms;
}

void ticker_set_count(ticker_handle_t handle, int16_t count)
{
    ticker_datas_t *tmp = (ticker_datas_t *)handle;
    if (count < 0)
        return;
    if (handle == NULL)
        return;
    if (tmp->tick_p == NULL)
        return;
    tmp->tick_t_mode_flg = count;
}

int16_t ticker_get_count(ticker_handle_t handle)
{
    ticker_datas_t *tmp = (ticker_datas_t *)handle;
    if (handle == NULL)
        return -1;
    if (tmp->tick_p == NULL)
        return -1;
    return tmp->tick_t_mode_flg;
}

void ticker_heartbeat_ms(uint8_t _ms)
{
    tic_count++;
    tic_flg = 1;
    ticker_delay_t -= _ms;
}

void ticker_task_handler()
{
    static uint8_t i;
    static uint32_t _tic_count;
    if (ticker_init_flg == 0 || tic_flg == 0)
        return;
    _tic_count = tic_count;
    tic_count = 0;
    tic_flg = 0;

    for (i = 0; i < task_max_num; i++)
    {
        if (_tic_dat[i].tick_t_mode_flg < 0) // 未注册或未开启
            continue;
        _tic_dat[i].tick_t_count += _tic_count;
        // 注册了
        if (_tic_dat[i].tick_t_count < _tic_dat[i].tick_t_count_max) // 定时未到
            continue;
        _tic_dat[i].tick_t_count -= _tic_dat[i].tick_t_count_max; // 定时到了减去一次计时
        if (_tic_dat[i].tick_p == NULL)                           // 回调函数为空
        {
            _tic_dat[i].tick_t_mode_flg = -1;
            continue;
        }
        _tic_dat[i].tick_p(&_tic_dat[i].ticker_userdata); // 调用回调
        if (_tic_dat[i].tick_t_mode_flg != 0)             // 不是无限次执行
        {
            _tic_dat[i].tick_t_mode_flg--;        // 次数减1
            if (_tic_dat[i].tick_t_mode_flg == 0) // 执行结束
            {
                if (_tic_dat[i].detach_cb != NULL)
                    _tic_dat[i].detach_cb(&_tic_dat[i].ticker_userdata);
                _tic_dat[i].detach_cb = NULL;
                _tic_dat[i].tick_p = NULL; // 注销任务
                _tic_dat[i].tick_t_mode_flg = -1;
            }
        }
    }
}

void delay(uint32_t ms)
{
    uint32_t timer_count;
    if (timer_get_count != NULL)
        timer_count = _timer_get_count();
    ticker_delay_t = ms;
    while (ticker_delay_t > 0)
    {
        ticker_task_handler();
        if (delay_cb != NULL)
            delay_cb(&delay_userdata);
    }
    if (timer_get_count == NULL)
        return;
    if (_count_mode == count_down)
    {
        while (_timer_get_count() > timer_count)
        {
            ticker_task_handler();
            if (delay_cb != NULL)
                delay_cb(&delay_userdata);
        }
        return;
    }
    while (_timer_get_count() < timer_count)
    {
        ticker_task_handler();
        if (delay_cb != NULL)
            delay_cb(&delay_userdata);
    }
}

#endif
